# primitive interactive 3D cube rendered as ASCII

SCREEN_W: 40 .
SCREEN_H: 30 .
FOV: 10 .
N: 16 .
NN: N -1 * .
N2: N 2 * .
SHIFT: 5 .

~8
  ~screen:8000
  ~tmp:0
~0

clearScreen:
  SCREEN_W SCREEN_H *

  ~8
  $screen>tmp
  ~0

  @'
    ~8
    " " $:tmp
    $>tmp
    ~0
    --
  .

  ^
.

printScreen:
  ~8
  $screen>tmp
  ~0
  SCREEN_H

  @'
    SCREEN_W

    @'
      ~8
      $tmp $0 -> ->
      $>tmp
      ~0
      --
    .
    ^

    10 ->

    --
  .

  ^
.

setPixel: # in: x y
  $1 SCREEN_W < $1 SCREEN_H < && ?
    SCREEN_W * +

    ~8
    $screen>tmp
    ~0

    @'
      ~8 $>tmp ~0
      --
    .

    ~8
    "." $:tmp
    ~0
    ^
  ;
    ^ ^
  .
.

perspective: # in: coord dist
  >< FOV * >< //
.

drawPoint3D: # in: x y z
  $2 $1 perspective SCREEN_W 2 / +
  $2 $2 perspective SCREEN_H 2 / +
  setPixel
  ^ ^ ^
.

drawLine3D: # in: x1 y1 z1 x2 y2 z2 n 

  $6 $4 + 2 //
  $6 $4 + 2 //
  $6 $4 + 2 //

  $3 ?
    $6 $6 $6 $5 $5 $5 $9 -- drawLine3D
    $9 $9 $9 $5 $5 $5 $9 -- drawLine3D
  .

  drawPoint3D
  ^

  drawPoint3D
  drawPoint3D
.

~offsetX
~offsetY

PA: N  $offsetX + N $offsetY + N .
PB: NN $offsetX + N $offsetY + N .
PC: NN $offsetX + N $offsetY + N2 .
PD: N  $offsetX + N $offsetY + N2 .

PE: N  $offsetX + NN $offsetY + N .
PF: NN $offsetX + NN $offsetY + N .
PG: NN $offsetX + NN $offsetY + N2 .
PH: N  $offsetX + NN $offsetY + N2 .

0 $:offsetX
0 $:offsetY

@@
  clearScreen
  PA PB 4 drawLine3D
  PB PC 4 drawLine3D
  PC PD 4 drawLine3D
  PD PA 4 drawLine3D

  PA PE 4 drawLine3D
  PB PF 4 drawLine3D
  PC PG 4 drawLine3D
  PD PH 4 drawLine3D

  PE PF 4 drawLine3D
  PF PG 4 drawLine3D
  PG PH 4 drawLine3D
  PH PE 4 drawLine3D
  printScreen

  0 10 "enter command (w, s, a, d, q): " -->

  <-

  $0 "q" = ?
    !@
  ; $0 "d" = ?
    $offsetX SHIFT + $:offsetX
  ; $0 "a" = ?
    $offsetX SHIFT - $:offsetX
  ; $0 "s" = ?
    $offsetY SHIFT + $:offsetY
  ; $0 "w" = ?
    $offsetY SHIFT - $:offsetY
  . . . . .

  ^
.
